﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Zen4SyncDashboard.DAL;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Threading;

namespace Zen4SyncDashboard.ViewModel
{
    public class MergeSyncViewModel : BaseViewModel
    {
        #region - Bound Properties -

        /// <summary>
        /// All the internet objects stored in the model.
        /// </summary>
        public ObservableCollection<internet> Internets { get; private set; }
        /// <summary>
        /// internet to be added to the model by the <see cref="AddNewInternetCommand"/> command.
        /// </summary>
        public internet NewInternet { get; private set; }
        /// <summary>
        /// internet to be deleted by the <see cref="DeleteCurrentInternetCommand"/> command.
        /// </summary>
        public internet CurrentInternet { get; set; }
        /// <summary>
        /// All the publisher objects stored in the model.
        /// </summary>
        public ObservableCollection<publisher> Publishers { get; private set; }
        /// <summary>
        /// All the NetworkType objects stored in the model.
        /// </summary>
        public networkType[] NetworkTypes { get; private set; }
        /// <summary>
        /// All the SecurityType objects stored in the model.
        /// </summary>
        public securityType[] SecurityTypes { get; private set; }
        /// <summary>
        /// All the ExchangeType objects stored in the model.
        /// </summary>
        public exchangeType[] ExchangeTypes { get; private set; }
        /// <summary>
        /// All the SnapshotTransferType objects stored in the model.
        /// </summary>
        public snapshotTransferType[] SnapshotTransferTypes { get; private set; }
        /// <summary>
        /// publisher to be added to the model by the <see cref="AddNewPublisherCommand"/> command.
        /// </summary>
        public publisher NewPublisher { get; private set; }
        /// <summary>
        /// publisher to be deleted by the <see cref="DeleteCurrentPublisherCommand"/> command.
        /// </summary>
        public publisher CurrentPublisher { get; set; }
        /// <summary>
        /// All the distributor objects stored in the model.
        /// </summary>
        public ObservableCollection<distributor> Distributors { get; private set; }
        /// <summary>
        /// distributor to be added to the model by the <see cref="AddNewDistributorCommand"/> command.
        /// </summary>
        public distributor NewDistributor { get; private set; }
        /// <summary>
        /// distributor to be deleted from the model by the <see cref="DeleteCurrentDistributorCommand"/> command
        /// </summary>
        public distributor CurrentDistributor { get; set; }
        /// <summary>
        /// syncSession to be added to the model by the <see cref="AddNewSyncSessionCommand"/> command.
        /// </summary>
        public syncSession NewSyncSession { get; private set; }
        /// <summary>
        /// All the syncSession objects stored in the model.
        /// </summary>
        public ObservableCollection<syncSession> SyncSessions { get; private set; }

        #endregion - Bound Properties -

        #region - Commands -

        /// <summary>
        /// Adds the <see cref="NewInternet"/> object to the model.<br/>
        /// Can be executed if the <see cref="NewInternet"/> is valid.
        /// </summary>
        public RelayCommand AddNewInternetCommand { get; private set; }
        /// <summary>
        /// Deletes the <see cref="CurrentInternet"/> object from the model.<br/>
        /// Can be executed if <see cref="CurrentInternet"/> is not null.
        /// </summary>
        public RelayCommand DeleteCurrentInternetCommand { get; private set; }
        /// <summary>
        /// Adds the <see cref="NewPublisher"/> object to the model.<br/>
        /// Can be executed if the <see cref="NewPublisher"/> is valid.
        /// </summary>
        public RelayCommand AddNewPublisherCommand { get; private set; }
        /// <summary>
        /// Deletes the <see cref="CurrentPublisher"/> object from the model.<br/>
        /// Can be executed if <see cref="CurrentPublisher"/> is not null.
        /// </summary>
        public RelayCommand DeleteCurrentPublisherCommand { get; private set; }
        /// <summary>
        /// Adds the <see cref="NewDistributor"/> object to the model.<br/>
        /// Can be execute if the <see cref="NewDistributor"/> is valid.
        /// </summary>
        public RelayCommand AddNewDistributorCommand { get; private set; }
        /// <summary>
        /// Deletes the <see cref="CurrentDistributor"/> object from the model.<br/>
        /// Can be executed if the <see cref="CurrentDistributor"/> is not null.
        /// </summary>
        public RelayCommand DeleteCurrentDistributorCommand { get; private set; }
        /// <summary>
        /// Adds the <see cref="NewSyncSession"/> object to the model.<br/>
        /// Can be executed if the <see cref="NewSeyncSession"/> is valid.
        /// </summary>
        public RelayCommand AddNewSyncSessionCommand { get; private set; }

        #endregion - Commands -

        public MergeSyncViewModel()
        {
            InitializeBoundProperties();
            InitializeCommands();
        }

        #region - DAL Methods -

        private bool ValidateNewInternet()
        {
            return NewInternet.IsValid();
        }

        private void AddNewInternet()
        {
            Zen4SyncModel.Internet.Add(NewInternet);

            Internets.Add(NewInternet);

            NewInternet = Zen4SyncModel.Internet.Create();
            OnPropertyChanged("NewInternet");
        }

        private bool CanDeleteCurrentInternet()
        {
            return CurrentInternet != null;
        }

        private void DeleteCurrentInternet()
        {
            Zen4SyncModel.Internet.Delete(CurrentInternet);
            Internets.Remove(CurrentInternet);
        }

        private bool ValidateNewPublisher()
        {
            return NewPublisher.IsValid();
        }

        private void AddNewPublisher()
        {
            Zen4SyncModel.Publisher.Add(NewPublisher);

            Publishers.Add(NewPublisher);

            NewPublisher = Zen4SyncModel.Publisher.Create();
            OnPropertyChanged("NewPublisher");
        }

        private bool CanDeleteCurrentPublisher()
        {
            return CurrentPublisher != null;
        }

        private void DeleteCurrentPublisher()
        {
            Zen4SyncModel.Publisher.Delete(CurrentPublisher);
            Publishers.Remove(CurrentPublisher);
        }

        private bool ValidateNewDistributor()
        {
            return NewDistributor.IsValid();
        }

        private void AddNewDistributor()
        {
            Zen4SyncModel.Distributor.Add(NewDistributor);

            Distributors.Add(NewDistributor);

            NewDistributor = Zen4SyncModel.Distributor.Create();
            OnPropertyChanged("NewDistributor");
        }

        private bool CanDeleteCurrentDistributor()
        {
            return CurrentDistributor != null;
        }

        private void DeleteCurrentDistributor()
        {
            Zen4SyncModel.Distributor.Delete(CurrentDistributor);
            Distributors.Remove(CurrentDistributor);
        }

        private bool ValidateNewSyncSession()
        {
            return NewSyncSession.IsValid();
        }

        private void AddNewSyncSession()
        {
            Zen4SyncModel.SyncSession.Add(NewSyncSession);

            SyncSessions.Add(NewSyncSession);

            NewSyncSession = Zen4SyncModel.SyncSession.Create();
            OnPropertyChanged("NewSyncSession");
        }

        #endregion - DAL Methods -

        #region - Initialization Methods -

        private void InitializeBoundProperties()
        {
            NewInternet = Zen4SyncModel.Internet.Create();
            NewPublisher = Zen4SyncModel.Publisher.Create();
            NewDistributor = Zen4SyncModel.Distributor.Create();
            NewSyncSession = Zen4SyncModel.SyncSession.Create();

            Task.Factory
                .StartNew(() =>
                {
                    base.SetWorkStatus("Fetching Internet Servers...");
                    Internets = Zen4SyncModel.Internet.GetAll();
                    OnPropertyChanged("Internets");

                    base.SetWorkStatus("Fetching Publishers...");
                    Publishers = Zen4SyncModel.Publisher.GetAll();
                    OnPropertyChanged("Publishers");

                    base.SetWorkStatus("Fetching Distributors...");
                    Distributors = Zen4SyncModel.Distributor.GetAll();
                    OnPropertyChanged("Distributors");

                    base.SetWorkStatus("Fetching Network Types...");
                    NetworkTypes = Zen4SyncModel.NetworkType.GetAll();
                    OnPropertyChanged("NetworkTypes");

                    base.SetWorkStatus("Fetching Security Types...");
                    SecurityTypes = Zen4SyncModel.SecurityType.GetAll();
                    OnPropertyChanged("SecurityTypes");

                    base.SetWorkStatus("Fetching Exchange Types...");
                    ExchangeTypes = Zen4SyncModel.ExchangeType.GetAll();
                    OnPropertyChanged("ExchangeTypes");

                    base.SetWorkStatus("Fetching Snapshot Transfer Types...");
                    SnapshotTransferTypes = Zen4SyncModel.SnapshotTransferType.GetAll();
                    OnPropertyChanged("SnapshotTransferTypes");

                    base.SetWorkStatus("Fetching Merge Synchronizations...");
                    SyncSessions = Zen4SyncModel.SyncSession.GetAll();
                    OnPropertyChanged("SyncSessions");

                    base.SetWorkStatus(false);
                });
        }
        
        private void InitializeCommands()
        {
            AddNewInternetCommand = new RelayCommand(
                param => AddNewInternet(),
                param => ValidateNewInternet());

            DeleteCurrentInternetCommand = new RelayCommand(
                param => DeleteCurrentInternet(),
                param => CanDeleteCurrentInternet());

            AddNewPublisherCommand = new RelayCommand(
                param => AddNewPublisher(),
                param => ValidateNewPublisher());

            DeleteCurrentPublisherCommand = new RelayCommand(
                param => DeleteCurrentPublisher(),
                param => CanDeleteCurrentPublisher());

            AddNewDistributorCommand = new RelayCommand(
                param => AddNewDistributor(),
                param => ValidateNewDistributor());

            DeleteCurrentDistributorCommand = new RelayCommand(
                param => DeleteCurrentDistributor(),
                param => CanDeleteCurrentDistributor());

            AddNewSyncSessionCommand = new RelayCommand(
                param => AddNewSyncSession(),
                param => ValidateNewSyncSession());
        }

        #endregion - Initialization Methods -
    }
}
